from threading import Thread
from threading import Event
from urllib2 import urlopen
from mbserver.server.request.controller import process_results
from mbserver.server.lib import utils
from mbserver.source.models import Source

import logging
log = logging.getLogger('metabus')

class WorkerThread ( Thread ):
    """
        This thread handles the IO jobs. It performs all the requests for 
        keyword search.
    """

    def __init__( self, requests, bg_requests, responses, timeout=0.2, **kwds ):
        Thread.__init__(self, **kwds)
        self.timeout = timeout
        self.requests = requests
        self.bg_requests = bg_requests
        self.responses = responses
        self._dismissed = Event()
    
    def run ( self ):

        # Keep serving until be killed       
        while True:

            # Finish Thread if dismiss was seted
            if(self._dismissed.isSet()):
                break

            # Get a url to request
            # The time out is important to give the thread a chance to finish
            try:
                search = self.requests.get(timeout = self.timeout)
            except:
                try:
                    search = self.bg_requests.get_nowait()
                except:
                    continue
           
            url = utils.get_url(search['source'], search['keyword'])
            if url.startswith(r'http://'):
                try:
                    log.debug("Opening URL: %s", url)
                    self.responses.put( (search['source'], urlopen(url).read(), search['keyword']) )
                except Exception, e:
                    log.error("Error opening source '(id:%s) %s' for searching. %s" % (search['source'].id, search['source'].name, e))

    def dismiss ( self ):
        self._dismissed.set()

class ParserThread ( Thread ):
    """
        This thread do the parsing of all documents retrieved by the 
        WorkerThread. Only one of this thread is need per process.
    """

    def __init__( self, docs, timeout=0.2, **kwds ):
        Thread.__init__(self, **kwds)
        self.timeout = timeout
        self.docs = docs
        self._dismissed = Event()

    def run ( self ):
        
        # parse
        while True:
            # Finish Thread if dismiss was seted
            if(self._dismissed.isSet()):
                break

            # Parse the document
            # The time out is important to give the tread a chance to finish
            try:
                source, doc, keyword = self.docs.get(timeout = self.timeout)
                results = []

                parser = source.parser.get_parser()
                parser.reset()
                parser.feed(doc)
                count = 1
                for item in parser.items:
                    results.append({
                        'title': item.get('title')[:255],
                        'description': item.get('description')[:255],
                        'link': item.get('link')[:255],
                        'order': count
                    })
                    count += 1
                process_results(source, results, keyword)
            except:
                continue
            else:
                pass

    def dismiss ( self ):
        self._dismissed.set() 
